﻿// <copyright file="BlogGenericService.cs" company="Clever Software">
// Copyright (c) 2013, 2014 All Right Reserved, http://www.cleversoftware.by
//
// This source is subject to the Microsoft Permissive License.
// Please see the License.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// </copyright>
// <author>Clever Software</author>
// <email>info@cleversoftware.by</email>
// <date>2014-02-04</date> 
// <summary>CleverCMS source code</summary>

namespace CleverCMS.Blog.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Data.Entity;
    using CleverCMS.Blog.Data;

    /// <summary>
    /// Base class for all services.
    /// </summary>
    /// <typeparam name="T">Class that derives from <see cref="MVCBlog.Core.Entities.EntityBase"/>.</typeparam>
    public abstract class BlogGenericService<T> : IBlogGenericService<T> where T : class//MVCBlog.Core.Entities.EntityBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GenericEntityService&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="repository">The <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.</param>
        /// <param name="unitOfWork">The <see cref="IUnitOfWork"/>.</param>
        protected BlogGenericService(IBlogGenericRepository<T> repository)
        {
            this.Repository = repository;
        }

        /// <summary>
        /// Gets or sets the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        protected IBlogGenericRepository<T> Repository { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="IUnitOfWork"/>.
        /// </summary>
        //protected IUnitOfWork UnitOfWork { get; set; }

        public IQueryable<T> Get(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
        {
            IQueryable<T> query = Repository.LoadAll();

            if (filter != null)
                query = query.Where(filter);

            foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                query = query.Include(includeProperty);

            if (orderBy != null)
                return orderBy(query);
            else
                return query;
        }

        /// <summary>
        /// Adds the given element to the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <param name="entity">The element to add.</param>
        public virtual void Add(T entity)
        {
            this.Add(entity, true);
        }

        /// <summary>
        /// Adds the given element to the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <param name="entity">The element to add.</param>
        /// <param name="saveChanges">Determines wheather changes should be saved.</param>
        internal void Add(T entity, bool saveChanges)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            this.Repository.Save(entity, true);

        }

        /// <summary>
        /// Deletes the given element from the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <param name="entity">The element to delete.</param>
        public virtual void Delete(T entity)
        {
            this.Delete(entity, true);
        }

        /// <summary>
        /// Deletes the given element from the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <param name="entity">The element to delete.</param>
        /// <param name="saveChanges">Determines wheather changes should be saved.</param>
        internal void Delete(T entity, bool saveChanges)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            this.Repository.Delete(entity);

        }

        /// <summary>
        /// Updates the given element in the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <param name="entity">The element to update.</param>
        public virtual void Update(T entity)
        {
            this.Update(entity, false);
        }

        /// <summary>
        /// Updates the given element in the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <param name="entity">The element to update.</param>
        /// <param name="saveChanges">Determines wheather changes should be saved.</param>
        internal void Update(T entity, bool isNew)
        {
            if (entity == null)
                throw new ArgumentNullException("entity");

            this.Repository.Save(entity, isNew);
        }

        /// <summary>
        /// Returns the <see cref="MVCBlog.Core.Entities.EntityBase"/> with the given id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns>The <see cref="MVCBlog.Core.Entities.EntityBase"/> with the given id.</returns>
        public virtual T GetById(object id)
        {
            var entity = this.Repository.Load(id);
            return entity;
        }

        /// <summary>
        /// Returns an <see cref="IEnumerable{T}"/> from the <see cref="MVCBlog.Core.Repository.IRepository{T}"/>.
        /// </summary>
        /// <returns>
        /// The <see cref="IEnumerable{T}"/> of all elements.
        /// </returns>
        public virtual IQueryable<T> GetAll()
        {
            return this.Repository.LoadAll();
        }

    }
}